using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using Admin.NET.Application.Entity.Business;
using Admin.NET.Application.Service.Plugin.Dto;
using Admin.NET.Application.Util;
using Admin.NET.Core;
using Admin.NET.Core.Service;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using Mapster;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;

namespace Admin.NET.Application.Service.Plugin;

/// <summary>
/// 协议插件管理
/// </summary>
[ApiDescriptionSettings(new string[] { "业务应用" }, Order = 100)]
public class AggrementPluginService : IDynamicApiController, ITransient, IPrivateDependency
{
	private readonly SqlSugarRepository<AggrementPluginManage> _rep;

	private readonly SysFileService _sysFileService;

	public AggrementPluginService(SqlSugarRepository<AggrementPluginManage> rep, SysFileService sysFileService)
	{
		_rep = rep;
		_sysFileService = sysFileService;
	}

	/// <summary>
	/// 获取插件列表
	/// </summary>
	/// <param name="input"></param>
	/// <returns></returns>
	[HttpGet("/aggrementplugin/page")]
	public async Task<dynamic> Page([FromQuery] AggrementPluginInput input)
	{
		ISugarQueryable<AggrementPluginManage> query = _rep.Context.Queryable<AggrementPluginManage>().WhereIF(!string.IsNullOrWhiteSpace(input.Name), (AggrementPluginManage u) => u.Name.Contains(input.Name));
		query = query.OrderBuilder(input);
		SqlSugarPagedList<AggrementPluginOutput> result = await query.Select((AggrementPluginManage u) => new AggrementPluginOutput
		{
			AssemblyName = u.AssemblyName,
			CreateTime = u.CreateTime,
			Id = u.Id,
			Name = u.Name,
			Path = u.Path,
			Remark = u.Remark,
			EParams = u.EParams
		}).ToPagedListAsync(input.Page, input.PageSize);
		if (result.Items.Count() > 0)
		{
			foreach (AggrementPluginOutput item in result.Items)
			{
				try
				{
					IAggrementPlugin service = AggrementPluginUtil.GetPluginService(item.AssemblyName, item.Path);
					if (service != null)
					{
						item.Status = service.IsRunning();
					}
				}
				catch (Exception)
				{
				}
			}
		}
		return result;
	}

	/// <summary>
	/// 上传dll
	/// </summary>
	/// <param name="file"></param>
	/// <returns></returns>
	[HttpPost("/aggrementplugin/upload")]
	public async Task<FileOutput> UploadPluginDLL([Required] IFormFile file)
	{
		return await _sysFileService.UploadFile(file, "Plugin/Aggrement");
	}

	/// <summary>
	/// 添加插件
	/// </summary>
	/// <param name="input"></param>
	/// <returns></returns>
	[HttpPost("/aggrementplugin/add")]
	public async Task AddPlugin(AddAggrementPluginInput input)
	{
		if (await _rep.IsAnyAsync((AggrementPluginManage a) => a.Name == input.Name))
		{
			throw Oops.Bah("当前插件名称已存在");
		}
		AggrementPluginManage entity = input.Adapt<AggrementPluginManage>();
		await _rep.InsertAsync(entity);
		Dictionary<string, string> plugin = new Dictionary<string, string> { { entity.AssemblyName, entity.Path } };
		AggrementPluginUtil.Init(plugin, out var msg);
		if (!string.IsNullOrWhiteSpace(msg))
		{
			throw Oops.Bah(msg);
		}
	}

	/// <summary>
	/// 编辑插件
	/// </summary>
	/// <param name="input"></param>
	/// <returns></returns>
	[HttpPost("/aggrementplugin/edit")]
	public async Task EditPlugin(EditAggrementPluginInput input)
	{
		if (await _rep.IsAnyAsync((AggrementPluginManage a) => a.Id != input.Id && a.Name == input.Name))
		{
			throw Oops.Bah("当前插件名称已存在");
		}
		AggrementPluginManage entity = input.Adapt<AggrementPluginManage>();
		await _rep.UpdateAsync(entity);
		Dictionary<string, string> plugin = new Dictionary<string, string> { { entity.AssemblyName, entity.Path } };
		AggrementPluginUtil.Init(plugin, out var msg);
		if (!string.IsNullOrWhiteSpace(msg))
		{
			throw Oops.Bah(msg);
		}
	}

	/// <summary>
	/// 删除插件
	/// </summary>
	/// <param name="input"></param>
	/// <returns></returns>
	[HttpPost("/aggrementplugin/delete")]
	public async Task DeletePlugin(DeleteAggrementPluginInput input)
	{
		AggrementPluginManage entity = await (from w in _rep.Context.Queryable<AggrementPluginManage>()
			where w.Id == input.Id
			select w).FirstAsync();
		if (entity == null)
		{
			throw Oops.Bah("当前插件不存在或已被删除");
		}
		await _rep.DeleteAsync(entity);
		IAggrementPlugin service = AggrementPluginUtil.GetPluginService(entity.AssemblyName, entity.Path);
		if (service == null)
		{
			throw Oops.Bah("插件加载失败");
		}
		var (status, msg) = service.Stop();
		if (!status)
		{
			throw Oops.Bah(msg);
		}
		AggrementPluginUtil._pluginDic.Remove(entity.AssemblyName);
	}

	/// <summary>
	/// 启动插件
	/// </summary>
	/// <param name="Id"></param>
	/// <returns></returns>
	[HttpPost("/aggrementplugin/start")]
	public async Task StartPlugin([FromQuery] long Id)
	{
		AggrementPluginManage plugin = _rep.GetById(Id);
		if (plugin == null)
		{
			throw Oops.Bah("当前插件不存在或已被删除");
		}
		IAggrementPlugin service = AggrementPluginUtil.GetPluginService(plugin.AssemblyName, plugin.Path);
		if (service == null)
		{
			throw Oops.Bah("插件加载失败");
		}
		var (status, msg) = service.Start(plugin.EParams);
		if (!status)
		{
			throw Oops.Bah(msg);
		}
		await (from s in _rep.Context.Updateable<AggrementPluginManage>().SetColumns((AggrementPluginManage s) => s.Status == 1)
			where s.Id == plugin.Id
			select s).ExecuteCommandAsync();
	}

	/// <summary>
	/// 停止插件
	/// </summary>
	/// <param name="Id"></param>
	/// <returns></returns>
	[HttpPost("/aggrementplugin/stop")]
	public async Task StopPlugin([FromQuery] long Id)
	{
		AggrementPluginManage plugin = _rep.GetById(Id);
		if (plugin == null)
		{
			throw Oops.Bah("当前插件不存在或已被删除");
		}
		IAggrementPlugin service = AggrementPluginUtil.GetPluginService(plugin.AssemblyName, plugin.Path);
		if (service == null)
		{
			throw Oops.Bah("插件加载失败");
		}
		var (status, msg) = service.Stop();
		if (!status)
		{
			throw Oops.Bah(msg);
		}
		await (from s in _rep.Context.Updateable<AggrementPluginManage>().SetColumns((AggrementPluginManage s) => s.Status == 0)
			where s.Id == plugin.Id
			select s).ExecuteCommandAsync();
	}

	[HttpGet("/aggrementplugin/all")]
	public async Task<dynamic> GetAllPlugin()
	{
		return await (from s in _rep.AsQueryable()
			select new { s.Id, s.Name }).ToListAsync();
	}
}
